﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Threading;
using System.Collections;

namespace curbside.Core.Utility.Net
{
    /// <summary>
    /// HttpWebRequest帮助类
    /// </summary>
    public class HttpWebRequestHelper
    {
        /// <summary>
        /// 快速请求指定url资源的资源（主要用于模拟压力测试）
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="threadNum">线程数</param>
        /// <param name="millisecondsTimeout">系统反应时间</param>
        public static void FastWebRequest(string url, int threadNum, int millisecondsTimeout)
        {
            FastWebRequest(url, "GET", null, threadNum, millisecondsTimeout);
        }

        /// <summary>
        /// 快速请求指定url资源的资源（主要用于模拟压力测试）
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="method">请求资源方法</param>
        /// <param name="urlParams">请求资源使用的参数</param>
        /// <param name="threadNum">线程数</param>
        /// <param name="millisecondsTimeout">系统反应时间</param>
        public static void FastWebRequest(string url, string method, string urlParams, int threadNum, int millisecondsTimeout)
        {
            ServicePointManager.DefaultConnectionLimit = 1000;

            //准备请求所使用的参数
            Hashtable ht = new Hashtable();
            ht.Add("url", url);
            ht.Add("method", method);
            ht.Add("urlParams", urlParams);

            while (true)
            {
                for (int i = 0; i < threadNum; i++)
                {
                    Thread t = new Thread(new ParameterizedThreadStart(GetHttpResponse));
                    t.Start(ht);
                }

                Thread.Sleep(millisecondsTimeout);
            }
        }

        /// <summary>
        /// 使用GET方式请求指定url的资源
        /// 对响应进行UTF8编码
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <returns></returns>
        public static string GetHttpTextResponse(string url)
        {
            return Encoding.UTF8.GetString(GetHttpResponse(url, "GET", null));
        }

        /// <summary>
        /// 使用GET方式请求指定url的资源
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="encode">编码方式</param>
        /// <returns></returns>
        public static string GetHttpTextResponse(string url, Encoding encode)
        {
            return encode.GetString(GetHttpResponse(url, "GET", null));
        }

        /// <summary>
        /// 请求指定URL资源
        /// 对响应进行UTF8编码
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="method">请求方式</param>
        /// <param name="urlParams">请求参数</param>
        /// <returns></returns>
        public static string GetHttpTextResponse(string url, string method, string urlParams)
        {
            return Encoding.UTF8.GetString(GetHttpResponse(url, method, urlParams));
        }

        /// <summary>
        /// 请求指定URL资源
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="encode">编码方式</param>
        /// <param name="method">请求方式</param>
        /// <param name="urlParams">请求参数</param>
        /// <returns></returns>
        public static string GetHttpTextResponse(string url, string method, string urlParams, Encoding encode)
        {
            return encode.GetString(GetHttpResponse(url, method, urlParams));
        }

        /// <summary>
        /// 得到请求响应字节数组
        /// </summary>
        /// <param name="url">资源地址</param>
        /// <param name="method">请求方式</param>
        /// <param name="urlParam">请求参数</param>
        /// <returns></returns>
        public static byte[] GetHttpResponse(string url, string method, string urlParam)
        {
            if (url.StartsWith("https", StringComparison.CurrentCultureIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
            }

            //创建请求
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            request.KeepAlive = false;
            request.ContentType = "application/x-www-form-urlencoded";
            request.AllowAutoRedirect = true;
            request.Credentials = CredentialCache.DefaultCredentials;
            byte[] param;
            if (string.Compare("post", method, false) == 0
                && !string.IsNullOrEmpty(urlParam)
                && !string.IsNullOrEmpty(urlParam.Trim()))
            {
                urlParam = urlParam.Trim();
                param = Encoding.UTF8.GetBytes(urlParam);
                request.ContentLength = param.Length;
                using (Stream s = request.GetRequestStream())
                {
                    s.Write(param, 0, param.Length);
                }
            }

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                if (response.StatusCode != HttpStatusCode.OK) return null;
                else return getBytesFromResponse(response);
            }
        }

        /// <summary>
        /// 请求资源
        /// </summary>
        /// <param name="parameter"></param>
        private static void GetHttpResponse(object parameter)
        {
            Hashtable ht = parameter as Hashtable;
            string url = ht["url"] as string;
            string method = ht["method"] as string;
            string urlParams = ht["urlParams"] as string;
            GetHttpResponse(url, method, urlParams);
        }

        //证书验证
        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }

        /// <summary>
        /// 从响应流中得到字节数组
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private static byte[] getBytesFromResponse(HttpWebResponse response)
        {
            byte[] result;
            using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
            {
                //ContentLength 属性包含与响应一起返回的 Content-Length 标头的值。
                //如果响应中未设置 Content-Length 标头，则将 ContentLength 设置为值 -1。
                int contentLenth = (int)response.ContentLength;
                if (contentLenth > 0)
                    result = reader.ReadBytes(contentLenth);
                else
                {
                    byte[] temp;
                    result = new byte[0];
                    int CountByte = 100000;
                    while (true)
                    {
                        temp = reader.ReadBytes(CountByte);
                        result = AppendByte(result, temp);
                        if (temp.Length != CountByte)
                            break;
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 合并 byte
        /// </summary>
        /// <param name="old">第一块</param>
        /// <param name="temp">第二块</param>
        /// <returns>返回块</returns>
        private static byte[] AppendByte(byte[] old, byte[] temp)
        {
            //目标区
            byte[] result = new byte[old.Length + temp.Length];
            //将old拷贝到目标区
            Buffer.BlockCopy(old, 0, result, 0, old.Length);
            //将temp拷贝到目标区 
            Buffer.BlockCopy(temp, 0, result, old.Length, temp.Length);

            old = null;
            temp = null;
            return result;
        }
    }
}
